昨天我們設計了前端整體架構,今天要開始實作第一個具體應用:Kyo-Dashboard OTP 管理介面。在接案過程中,客戶經常需要:
Kyo-Dashboard 要解決這些需求,提供完整的 OTP 服務管理功能。
核心功能模組
使用者體驗目標
1. 初始化 React + Vite 專案
cd apps
# 使用 Vite 建立 React + TypeScript 專案
pnpm create vite@latest kyo-dashboard --template react-ts
cd kyo-dashboard
# 安裝相依套件
pnpm install
2. 更新 package.json 配置
{
"name": "@kyong/kyo-dashboard",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"typescript": "^5.2.2",
"vite": "^5.2.0"
}
}
3. 安裝必要的前端套件
# UI 框架和工具
pnpm add @mantine/core @mantine/hooks @mantine/form @mantine/notifications
# 狀態管理
pnpm add zustand
# 路由
pnpm add react-router-dom
pnpm add -D @types/react-router-dom
# 型別共享
pnpm add @kyong/kyo-types
# 開發工具
pnpm add -D @types/node
4. 建立 TypeScript 配置
// tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/components/*": ["./src/components/*"],
"@/pages/*": ["./src/pages/*"],
"@/stores/*": ["./src/stores/*"],
"@/services/*": ["./src/services/*"],
"@/utils/*": ["./src/utils/*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
5. Node.js 環境配置
// tsconfig.node.json
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
6. 配置 Vite
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@/components': path.resolve(__dirname, './src/components'),
'@/pages': path.resolve(__dirname, './src/pages'),
'@/stores': path.resolve(__dirname, './src/stores'),
'@/services': path.resolve(__dirname, './src/services'),
'@/utils': path.resolve(__dirname, './src/utils')
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true
}
}
},
build: {
outDir: 'dist',
sourcemap: true
}
})
7. 建立標準目錄
# 建立專案結構
mkdir -p src/components src/pages src/stores src/services src/utils src/types src/assets
# 建立基礎檔案
touch src/components/index.ts
touch src/pages/index.ts
touch src/stores/index.ts
touch src/services/index.ts
touch src/utils/index.ts
8. 建立基礎文件結構
src/
├── components/ # 共用組件
│ ├── Layout/ # 佈局組件
│ ├── OtpForm/ # OTP 表單組件
│ └── index.ts # 組件匯出
├── pages/ # 頁面組件
│ ├── OtpSendPage.tsx
│ ├── OtpVerifyPage.tsx
│ └── index.ts
├── stores/ # Zustand 狀態管理
│ ├── otpStore.ts
│ ├── uiStore.ts
│ └── index.ts
├── services/ # API 服務層
│ ├── api.ts
│ ├── orpc.ts
│ └── index.ts
├── utils/ # 工具函數
│ ├── validators.ts
│ ├── formatters.ts
│ └── index.ts
├── assets/ # 靜態資源
├── App.tsx
├── main.tsx
└── index.css
9. Mantine 基礎設定
// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { MantineProvider } from '@mantine/core'
import { Notifications } from '@mantine/notifications'
import App from './App.tsx'
// Mantine CSS
import '@mantine/core/styles.css'
import '@mantine/notifications/styles.css'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<MantineProvider>
<Notifications />
<App />
</MantineProvider>
</React.StrictMode>,
)
10. 建立主要 App 組件
// src/App.tsx
import { AppShell, Container, Title } from '@mantine/core'
function App() {
return (
<AppShell
header={{ height: 64 }}
padding="md"
>
<AppShell.Header>
<Container size="xl" h="100%" p="md">
<Title order={2}>🔐 Kyo-Dashboard</Title>
</Container>
</AppShell.Header>
<AppShell.Main>
<Container size="md">
<Title order={1} ta="center" mt="xl">
歡迎使用 Kyo-System 管理台
</Title>
<p style={{ textAlign: 'center', marginTop: '1rem' }}>
OTP 驗證服務管理介面
</p>
</Container>
</AppShell.Main>
</AppShell>
)
}
export default App
11. ESLint 配置
// .eslintrc.cjs
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
12. 環境變數設定
# .env.example
VITE_API_URL=http://localhost:8000
VITE_ORPC_ENDPOINT=/api/orpc
VITE_APP_NAME=Kyo-Dashboard
VITE_APP_VERSION=0.1.0
# .env.local
VITE_API_URL=http://localhost:8000
VITE_ORPC_ENDPOINT=/api/orpc
VITE_APP_NAME=Kyo-Dashboard
VITE_APP_VERSION=0.1.0
13. 測試開發伺服器
# 啟動開發伺服器
pnpm run dev
# 在另一個終端機測試建置
pnpm run build
# 檢查 TypeScript 編譯
pnpm exec tsc --noEmit
# 執行 linting
pnpm run lint
14. 檢查 Monorepo 整合
# 回到根目錄
cd ../../
# 測試 Turborepo 建置
pnpm run build
# 確認前端專案包含在 workspace 中
pnpm -r list --depth=0
15. 全域樣式設定
/* src/index.css */
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
#root {
width: 100%;
margin: 0 auto;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
}
✅ React + Vite + TypeScript 專案初始化完成
✅ Mantine UI 框架整合與配置
✅ Monorepo workspace 整合測試
✅ TypeScript 路徑別名與型別配置
✅ ESLint 與開發工具設定
✅ 環境變數與建置配置
✅ 基礎專案結構建立
Day4 我們會開始實作第一個核心組件:OTP 發送表單,整合 @kyong/kyo-types
型別定義,並建立 Zustand 狀態管理來處理 API 呼叫。